package prender;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

/**
 * Control information for the top level http request.
 * @author Stone Zhong
 *
 */
class TopContext {
	private static final Logger logger = Logger.getLogger("TopContext");
	
	final ReentrantLock linkLock = new ReentrantLock();
	
	final ExecutorService threadPool;
	
	TopContext(
		PrintWriter writer, ExecutorService threadPool) {
		this.threadPool = threadPool;
		buffer = new WebBuffer(this, writer);
		monitor = new ExecutorCompletionService<AsyncContext>(this.threadPool);
	}
	
	
	MyRequest request;
	MyResponse response;
	
	private WebBuffer buffer;
	WebBuffer getBuffer() {
		return buffer;
	}
	
	
	volatile int asyncCount = 0;
	
	private ExecutorCompletionService<AsyncContext> monitor;
	ExecutorCompletionService<AsyncContext> getMonitor() {
		return monitor;
	}
	
	void initialize(HttpServletRequest request, HttpServletResponse response) throws IOException {
		MyResponse myResponse = new MyResponse(response);
		MyRequest  myRequest  = new MyRequest(request);
		
		myRequest.setTopContext(this);
		myRequest.setResponse(myResponse);
		
		WebBuffer wb = buffer.insertBuffer();
		myResponse.setWebBuffer(wb);
		
		this.request = myRequest;
		this.response = myResponse;
	}
	
	void waitForComplete() throws IOException {
		if (logger.isDebugEnabled()) {
			logger.debug("waitForComplete: enter");
			logger.debug(String.format("waitForComplete: myResponse = [%s]", response));
		}
		
		response.getWebBuffer().stopPending();
		
    	for (;;) {
    		if (logger.isDebugEnabled()) {
    			logger.debug(String.format("waitForComplete: asyncCount = %d", asyncCount));
    		}
    		if (asyncCount == 0) {
    			break;
    		}
    		try {
    			if (logger.isDebugEnabled()) {
    				logger.debug("waitForComplete: wait for async task to complete");
    			}
    			getMonitor().take();
    			asyncCount --;
    			if (logger.isDebugEnabled()) {
    				logger.debug("waitForComplete: ansync task completed");
    			}
    		} catch (InterruptedException e) {
				logger.error("waitForComplete: exception ignored", e);
    		}
    	}
    	
		if (logger.isDebugEnabled()) {
			this.buffer.dumpBuffersToLogger("waitForComplete");
		}
	}
}
